"""
邮件配置服务
处理邮件配置的CRUD操作、连接测试、邮件发送测试等业务逻辑
"""

import smtplib
import ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import func
from fastapi import HTTPException, status
from datetime import datetime, timedelta

from models.email_config import EmailConfig
from schemas.email_config import (
    EmailConfigCreate, EmailConfigUpdate, EmailConfigResponse, EmailConfigList,
    EmailConfigTest, EmailConfigTestResponse, EmailConfigStatistics,
    EmailSendTest, EmailSendTestResponse, EncryptionType
)


class EmailConfigService:
    """邮件配置服务类"""
    
    @staticmethod
    def create_email_config(db: Session, config_data: EmailConfigCreate, user_id: int) -> EmailConfig:
        """创建邮件配置"""
        # 检查名称是否已存在
        existing = db.query(EmailConfig).filter(
            EmailConfig.name == config_data.name,
            EmailConfig.user_id == user_id
        ).first()
        
        if existing:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="邮件配置名称已存在"
            )
        
        # 根据加密类型设置SSL和TLS字段
        use_ssl = config_data.encryption == EncryptionType.SSL
        use_tls = config_data.encryption == EncryptionType.STARTTLS

        # 创建邮件配置
        db_config = EmailConfig(
            name=config_data.name,
            smtp_host=config_data.smtp_host,
            smtp_port=config_data.smtp_port,
            username=config_data.username,
            password=config_data.password,  # 注意：实际应用中应该加密存储
            from_email=config_data.from_email,
            from_name=config_data.from_name,
            encryption=config_data.encryption.value,
            use_ssl=use_ssl,
            use_tls=use_tls,
            timeout=config_data.timeout,
            description=config_data.description,
            user_id=user_id
        )
        
        db.add(db_config)
        db.commit()
        db.refresh(db_config)
        return db_config
    
    @staticmethod
    def get_email_configs(
        db: Session, 
        user_id: int, 
        page: int = 1, 
        size: int = 10,
        search: Optional[str] = None,
        active_only: bool = False
    ) -> EmailConfigList:
        """获取邮件配置列表"""
        query = db.query(EmailConfig).filter(EmailConfig.user_id == user_id)
        
        # 搜索过滤
        if search:
            search_pattern = f"%{search}%"
            query = query.filter(EmailConfig.name.like(search_pattern))
        
        # 状态过滤
        if active_only:
            query = query.filter(EmailConfig.is_active == True)
        
        # 总数
        total = query.count()
        
        # 分页
        items = query.order_by(EmailConfig.created_at.desc()).offset((page - 1) * size).limit(size).all()
        
        # 计算总页数
        pages = (total + size - 1) // size
        
        return EmailConfigList(
            items=[EmailConfigResponse.from_orm(item) for item in items],
            total=total,
            page=page,
            size=size,
            pages=pages
        )
    
    @staticmethod
    def get_email_config(db: Session, config_id: int, user_id: int) -> Optional[EmailConfig]:
        """获取单个邮件配置"""
        return db.query(EmailConfig).filter(
            EmailConfig.id == config_id,
            EmailConfig.user_id == user_id
        ).first()
    
    @staticmethod
    def update_email_config(
        db: Session, 
        config_id: int, 
        config_data: EmailConfigUpdate, 
        user_id: int
    ) -> Optional[EmailConfig]:
        """更新邮件配置"""
        db_config = EmailConfigService.get_email_config(db, config_id, user_id)
        if not db_config:
            return None
        
        # 检查名称是否已存在（排除自己）
        if config_data.name:
            existing = db.query(EmailConfig).filter(
                EmailConfig.name == config_data.name,
                EmailConfig.user_id == user_id,
                EmailConfig.id != config_id
            ).first()
            
            if existing:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="邮件配置名称已存在"
                )
        
        # 更新字段
        update_data = config_data.dict(exclude_unset=True)
        for field, value in update_data.items():
            if field == 'encryption' and value:
                setattr(db_config, field, value.value)
                # 同时更新SSL和TLS字段
                setattr(db_config, 'use_ssl', value == EncryptionType.SSL)
                setattr(db_config, 'use_tls', value == EncryptionType.STARTTLS)
            else:
                setattr(db_config, field, value)
        
        db.commit()
        db.refresh(db_config)
        return db_config
    
    @staticmethod
    def delete_email_config(db: Session, config_id: int, user_id: int) -> bool:
        """删除邮件配置"""
        db_config = EmailConfigService.get_email_config(db, config_id, user_id)
        if not db_config:
            return False
        
        db.delete(db_config)
        db.commit()
        return True
    
    @staticmethod
    def toggle_email_config_status(db: Session, config_id: int, user_id: int) -> Optional[EmailConfig]:
        """切换邮件配置启用状态"""
        db_config = EmailConfigService.get_email_config(db, config_id, user_id)
        if not db_config:
            return None
        
        db_config.is_active = not db_config.is_active
        db.commit()
        db.refresh(db_config)
        return db_config

    @staticmethod
    def test_email_config(test_request: EmailConfigTest) -> EmailConfigTestResponse:
        """测试邮件配置连接"""
        try:
            # 创建SMTP连接
            if test_request.encryption == EncryptionType.SSL:
                # SSL连接
                context = ssl.create_default_context()
                server = smtplib.SMTP_SSL(
                    test_request.smtp_host,
                    test_request.smtp_port,
                    timeout=test_request.timeout,
                    context=context
                )
            else:
                # 普通连接或STARTTLS
                server = smtplib.SMTP(
                    test_request.smtp_host,
                    test_request.smtp_port,
                    timeout=test_request.timeout
                )

                if test_request.encryption == EncryptionType.STARTTLS:
                    server.starttls()

            # 尝试登录
            server.login(test_request.username, test_request.password)

            test_email_sent = False
            # 如果提供了测试邮箱，发送测试邮件
            if test_request.test_email:
                try:
                    msg = MIMEMultipart()
                    msg['From'] = test_request.from_email
                    msg['To'] = test_request.test_email
                    msg['Subject'] = "邮件配置测试"

                    body = "这是一封测试邮件，用于验证邮件配置是否正常工作。"
                    msg.attach(MIMEText(body, 'plain', 'utf-8'))

                    server.send_message(msg)
                    test_email_sent = True
                except Exception as e:
                    # 连接成功但发送失败
                    server.quit()
                    return EmailConfigTestResponse(
                        success=True,
                        message="SMTP连接成功，但测试邮件发送失败",
                        details={
                            "smtp_host": test_request.smtp_host,
                            "smtp_port": test_request.smtp_port,
                            "encryption": test_request.encryption.value,
                            "send_error": str(e)
                        },
                        test_email_sent=False
                    )

            server.quit()

            message = "SMTP连接成功"
            if test_email_sent:
                message += "，测试邮件发送成功"

            return EmailConfigTestResponse(
                success=True,
                message=message,
                details={
                    "smtp_host": test_request.smtp_host,
                    "smtp_port": test_request.smtp_port,
                    "encryption": test_request.encryption.value,
                    "username": test_request.username
                },
                test_email_sent=test_email_sent
            )

        except smtplib.SMTPAuthenticationError:
            return EmailConfigTestResponse(
                success=False,
                message="SMTP认证失败，请检查用户名和密码"
            )
        except smtplib.SMTPConnectError:
            return EmailConfigTestResponse(
                success=False,
                message="无法连接到SMTP服务器，请检查服务器地址和端口"
            )
        except smtplib.SMTPServerDisconnected:
            return EmailConfigTestResponse(
                success=False,
                message="SMTP服务器连接断开"
            )
        except Exception as e:
            return EmailConfigTestResponse(
                success=False,
                message=f"连接测试失败: {str(e)}"
            )

    @staticmethod
    def send_test_email(db: Session, send_request: EmailSendTest, user_id: int) -> EmailSendTestResponse:
        """发送测试邮件"""
        # 获取邮件配置
        config = EmailConfigService.get_email_config(db, send_request.config_id, user_id)
        if not config:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="邮件配置不存在"
            )

        if not config.is_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="邮件配置已禁用"
            )

        try:
            # 创建SMTP连接
            if config.encryption == "ssl":
                context = ssl.create_default_context()
                server = smtplib.SMTP_SSL(
                    config.smtp_host,
                    config.smtp_port,
                    timeout=config.timeout,
                    context=context
                )
            else:
                server = smtplib.SMTP(
                    config.smtp_host,
                    config.smtp_port,
                    timeout=config.timeout
                )

                if config.encryption == "starttls":
                    server.starttls()

            # 登录
            server.login(config.username, config.password)

            # 创建邮件
            msg = MIMEMultipart()
            msg['From'] = f"{config.from_name} <{config.from_email}>" if config.from_name else config.from_email
            msg['To'] = send_request.to_email
            msg['Subject'] = send_request.subject

            # 添加邮件内容
            msg.attach(MIMEText(send_request.content, 'plain', 'utf-8'))

            # 发送邮件
            result = server.send_message(msg)
            server.quit()

            return EmailSendTestResponse(
                success=True,
                message="测试邮件发送成功",
                details={
                    "from": config.from_email,
                    "to": send_request.to_email,
                    "subject": send_request.subject,
                    "config_name": config.name
                }
            )

        except Exception as e:
            return EmailSendTestResponse(
                success=False,
                message=f"邮件发送失败: {str(e)}"
            )

    @staticmethod
    def get_email_config_statistics(db: Session, user_id: int) -> EmailConfigStatistics:
        """获取邮件配置统计信息"""
        # 总数统计
        total = db.query(EmailConfig).filter(EmailConfig.user_id == user_id).count()

        # 启用状态统计
        active = db.query(EmailConfig).filter(
            EmailConfig.user_id == user_id,
            EmailConfig.is_active == True
        ).count()

        # 按加密类型统计
        encryption_stats = db.query(
            EmailConfig.encryption,
            func.count(EmailConfig.id).label('count')
        ).filter(EmailConfig.user_id == user_id).group_by(EmailConfig.encryption).all()

        by_encryption = {item.encryption: item.count for item in encryption_stats}

        # 最近7天新增
        seven_days_ago = datetime.now() - timedelta(days=7)
        recent_added = db.query(EmailConfig).filter(
            EmailConfig.user_id == user_id,
            EmailConfig.created_at >= seven_days_ago
        ).count()

        return EmailConfigStatistics(
            total=total,
            active=active,
            by_encryption=by_encryption,
            recent_added=recent_added
        )

    @staticmethod
    def get_active_email_configs(db: Session, user_id: int) -> List[EmailConfig]:
        """获取用户的所有启用的邮件配置"""
        return db.query(EmailConfig).filter(
            EmailConfig.user_id == user_id,
            EmailConfig.is_active == True
        ).order_by(EmailConfig.created_at.desc()).all()

    @staticmethod
    def get_default_email_config(db: Session, user_id: int) -> Optional[EmailConfig]:
        """获取用户的默认邮件配置（第一个启用的配置）"""
        return db.query(EmailConfig).filter(
            EmailConfig.user_id == user_id,
            EmailConfig.is_active == True
        ).order_by(EmailConfig.created_at.asc()).first()
